home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
001-025
/
disk_001
/
balls
/
balls.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
15KB
|
477 lines
#include <exec/types.h>
#include <libraries/mathffp.h>
#include <graphics/gfxbase.h>
#include <intuition/intuition.h>
#undef NULL
#include <stdio.h>
/*
** balls - a simulation of that kinetic thingy with three-d
** smooth shaded spheres with diffuse and specular
** reflections. It'd be nice if someone could add
** sound. A good demonstration of using the ffp
** math subroutines. I plan to add texture mapping
** to the spheres in the future.
**
**
** perry s. kivolowitz - ihnp4!ptsfa!well!perry
**
** not to be distributed for commercial purposes. any
** distribution must include this notice, please.
**
*/
#ifdef MY_DEBUG
FILE *dfp;
#endif
#define RADIUS 20 /* radius of the balls ve are goink to draw */
#define DEPTH 5 /* number of pixel planes */
#define NMAP 32 /* 2 to the DEPTH power */
#define AMBIENT 2 /* how much light on the dark side ofthe moon */
#define NSTEPS 6 /* how many discreet frames in bouncers */
#define SH 200 /* screen height */
#define SW 320 /* screen width */
#define WH (SH-10) /* window height */
#define WW SW /* window width */
#define MW (WW / 2) /* middle of window */
#define D (2 * RADIUS)
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
int MathBase;
int MathTransBase;
int is_cli = 0;
struct Window *w; /* window structure returned by exec */
struct Screen *s; /* screen structure returned by exec */
struct ColorMap *color_map; /* pointer to c_map returned by exec */
short displacements[D]; /* place for sphere's scanline dx's */
short surface[D]; /* place for spehre's scanline dz's */
extern int SPAdd() , SPSub() , SPMul() , SPDiv() , SPNeg() ;
extern int SPFix() , SPFlt() , SPCmp() , SPTst() , SPAbs() ;
extern int SPSqrt() , SPFieee() , SPTieee();
extern int SPSin() , SPCos() , SPPow();
union kludge {
float f;
int i;
};
struct bouncer {
struct RastPort rp;
struct BitMap bm;
int sx , sy;
} left[NSTEPS] , right[NSTEPS];
struct point {
union kludge x;
union kludge y;
union kludge z;
} light;
/*
** mask is a bit mask of things that I should close or deallocate
** when the program terminates for any reason. after opening or
** allocating some resource set the appropriate bit in mask.
*/
unsigned int mask = 0;
#define INTUITION 0x00000001
#define GRAPHICS 0x00000002
#define SCREEN 0x00000004
#define WINDOW 0x00000008
#define COLORMAP 0x00000010
#define MATH 0x00000020
#define MATHTRANS 0x00000040
int rastcount = 0; /* easy way to free rasters at termination */
struct NewScreen ns = { /*****************/
0 , /* LeftEdge */
0 , /* TopEdge */
SW , /* Width */
SH , /* Height */
DEPTH , /* Depth */
0 , /* DetailPen */
1 , /* BlockPen */
0 , /* ViewModes */
CUSTOMSCREEN , /* Type */
NULL , /* *Font */
" spheres by p.s.kivolowitz" , /* *DefaultTitle */
NULL , /* *Gadgets */
NULL /* *CustomBitMap */
}; /*****************/
struct NewWindow nw = { /*****************/
0 , /* LeftEdge */
10 , /* TopEdge */
WW , /* Width */
WH , /* Height */
-1 , /* DetailPen */
-1 , /* BlockPen */
CLOSEWINDOW , /* IDCMP---Flags */
WINDOWCLOSE /* F */
| BACKDROP /* l */
| BORDERLESS /* a */
| NOCAREREFRESH /* g */
| ACTIVATE , /* s */
NULL , /* *FirstGadget */
NULL , /* *CheckMark */
"(still under development)" ,/* *Title */
NULL , /* *Screen */ /* to be filled in */
NULL , /* *BitMap */
0 , /* MinWidth */
0 , /* MinHeight */
0 , /* MaxWidth */
0 , /* MaxHeight */
CUSTOMSCREEN /* Type */
}; /*****phew!!!*****/
float convert(i)
{
union kludge k;
k.i = SPTieee(i);
return(k.f);
}
degrad(degrees)
{
union kludge pi;
pi.f = 355.0 / 113.0; /* chinese approximation */
pi.i = SPMul(SPFieee(pi.i) , SPFlt(degrees));
return(SPDiv(SPFlt(180) , pi.i));
}
main(argc , argv)
char *argv[];
{
int i;
struct IntuiMessage *message;
if (argc) is_cli = 1;
#ifdef MY_DEBUG
if ((dfp = fopen("debug.file" , "w")) == NULL) {
if (is_cli) printf("can't open debugging file\n");
exit(1);
}
fprintf(dfp,"debugging information\n");
fflush(dfp);
#endif
if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)))
{
if (is_cli) printf("no graphics library!!!\n");
close_things();
exit(1);
}
mask |= GRAPHICS;
if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library"))) {
if (is_cli) printf("no intuition here!!\n");
close_things();
exit(1);
}
mask |= INTUITION;
if ((MathBase = OpenLibrary("mathffp.library" , 0)) == NULL) {
if (is_cli) printf("couldn't open mathffp library\n");
close_things();
exit(1);
}
mask |= MATH;
if ((MathTransBase = OpenLibrary("mathtrans.library" , 0)) == NULL) {
if (is_cli) printf("couldn't open mathtrans library\n");
close_things();
exit(1);
}
mask |= MATHTRANS;
allocate_rasters();
if ((s = (struct Screen *) OpenScreen(&ns)) == (struct Screen *) NULL) {
if (is_cli) printf("could not open the screen!\n");
close_things();
exit(2);
}
mask |= SCREEN;
nw.Screen = s;
if((w = (struct Window *)OpenWindow(&nw)) == (struct Window *) NULL) {
if (is_cli) printf("could not open the window!\n");
close_things();
exit(2);
}
mask |= WINDOW;
init_color_map();
light.x.f = 0.0;
light.y.f = light.x.f + 150.0 - light.x.f;
light.z.f = light.x.f + 25.0 - light.x.f;
light.x.i = SPFieee(light.x.i); /* */
light.y.i = SPFieee(light.y.i); /* convert light vector to FFP */
light.z.i = SPFieee(light.z.i); /* */
bres(RADIUS , displacements);
/*
** make the three bottom balls
*/
make_ball(w->RPort , MW - D , WH - RADIUS , -D , 0 , 0);
make_ball(w->RPort , MW , WH - RADIUS , 0 , 0 , 0);
make_ball(w->RPort , MW + D , WH - RADIUS , D , 0 , 0);
make_rotated_ball(&left[0] , -15 , MW - 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&right[0] , 15 , MW + 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&left[1] , -14 , MW - 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&right[1] , 14 , MW + 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&left[2] , -12 , MW - 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&right[2] , 12 , MW + 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&left[3] , -9 , MW - 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&right[3], 9 , MW + 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&left[4] , -5 , MW - 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&right[4], 5 , MW + 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&left[5] , 0 , MW - 2 * D , 10 , WH - 10 - RADIUS);
make_rotated_ball(&right[5], 0 , MW + 2 * D , 10 , WH - 10 - RADIUS);
ClipBlit(&left[0].rp,0,0,w->RPort,left[0].sx,left[0].sy,D,D,0xC0);
ClipBlit(&right[NSTEPS-1].rp,0,0,w->RPort,right[NSTEPS-1].sx,
right[NSTEPS-1].sy,D,D,0xC0);
message = (struct IntuiMessage *) GetMsg(w->UserPort);
while (!message || (message->Class != CLOSEWINDOW)) {
for (i = 1; i < NSTEPS; i++) {
Delay(2);
WaitBOVP(&s->ViewPort);
clear_rect(w->RPort,left[i-1].sx,left[i-1].sy,D,D);
ClipBlit(&left[i].rp,0,0,w->RPort,left[i].sx,left[i].sy,D,D,0xC0);
}
for (i = NSTEPS-2; i >= 0; i--) {
WaitBOVP(&s->ViewPort);
clear_rect(w->RPort,right[i+1].sx,right[i+1].sy,D,D);
ClipBlit(&right[i].rp,0,0,w->RPort,right[i].sx,right[i].sy,D,D,0xC0);
Delay(2);
}
Delay(1);
for (i = 1; i < NSTEPS; i++) {
Delay(2);
WaitBOVP(&s->ViewPort);
clear_rect(w->RPort,right[i-1].sx,right[i-1].sy,D,D);
ClipBlit(&right[i].rp,0,0,w->RPort,right[i].sx,right[i].sy,D,D,0xC0);
}
for (i = NSTEPS-2; i >= 0; i--) {
WaitBOVP(&s->ViewPort);
clear_rect(w->RPort,left[i+1].sx,left[i+1].sy,D,D);
ClipBlit(&left[i].rp,0,0,w->RPort,left[i].sx,left[i].sy,D,D,0xC0);
Delay(2);
}
Delay(1);
message = (struct IntuiMessage *) GetMsg(w->UserPort);
}
#ifdef MY_DEBUG
fclose(dfp);
#endif
close_things();
exit(0);
}
clear_rect(rp , sx , sy , dx , dy)
struct RastPort *rp;
{
ClipBlit(rp,sx,sy,rp,sx,sy,dx,dy,0x20);
}
make_rotated_ball(b , degrees , cx , cy , length)
struct bouncer *b;
{
int dx , dy;
dx = SPMul(SPFlt(length) , SPSin(degrad(abs(degrees))));
dy = SPMul(SPFlt(length) , SPCos(degrad(abs(degrees))));
b->sx = cx + ((degrees < 0) ? -SPFix(dx) : SPFix(dx));
b->sy = cy + SPFix(dy);
make_ball(&b->rp , RADIUS , RADIUS , b->sx - MW , WH - RADIUS - b->sy , 0);
b->sx -= RADIUS;
b->sy -= RADIUS;
}
close_things()
{
if (rastcount) deallocate_rasters();
if (mask & WINDOW) CloseWindow(w);
if (mask & SCREEN) CloseScreen(s);
if (mask & GRAPHICS) CloseLibrary(GfxBase);
(void) OpenWorkBench();
if (mask & INTUITION) CloseLibrary(IntuitionBase);
}
init_color_map()
{
static short map_values[NMAP] = {
/* format 0x0RGB */ /* ooooooooh ychhhhhh! fix this later! */
/* 0 */ 0x0430 ,
/* 1 */ 0x0FFF ,
/* 2 */ 0x0F01 ,
/* 3 */ 0x0F11 ,
/* 4 */ 0x0F12 ,
/* 5 */ 0x0F22 ,
/* 6 */ 0x0F23 ,
/* 7 */ 0x0F33 ,
/* 8 */ 0x0F34 ,
/* 9 */ 0x0F44 ,
/* 10 */ 0x0F45 ,
/* 11 */ 0x0F55 ,
/* 12 */ 0x0F56 ,
/* 13 */ 0x0F66 ,
/* 14 */ 0x0F67 ,
/* 15 */ 0x0F77 ,
/* 16 */ 0x0F78 ,
/* 17 */ 0x0F88 ,
/* 18 */ 0x0F89 ,
/* 19 */ 0x0F99 ,
/* 20 */ 0x0F9A ,
/* 21 */ 0x0FAA ,
/* 22 */ 0x0FAB ,
/* 23 */ 0x0FBB ,
/* 24 */ 0x0FBC ,
/* 25 */ 0x0FCC ,
/* 26 */ 0x0FCD ,
/* 27 */ 0x0FDD ,
/* 28 */ 0x0FDE ,
/* 29 */ 0x0FEE ,
/* 30 */ 0x0FEF ,
/* 31 */ 0x0FFF
};
LoadRGB4(&s->ViewPort , map_values , NMAP);
}
normalize(p)
struct point *p;
{
union kludge length;
int xsquared, ysquared, zsquared;
xsquared = SPMul (p -> x.i, p -> x.i);
ysquared = SPMul (p -> y.i, p -> y.i);
zsquared = SPMul (p -> z.i, p -> z.i);
length.i = SPSqrt (SPAdd (SPAdd (xsquared, ysquared), zsquared));
p->x.i = SPDiv(length.i , p->x.i);
p->y.i = SPDiv(length.i , p->y.i);
p->z.i = SPDiv(length.i , p->z.i);
}
make_ball(rp , basex , basey , cx , cy , cz)
struct RastPort *rp;
{
int I , scanline;
int twelve , x , y;
struct point H , l;
struct point pnt;
union kludge tmp , rad , d;
rad.i = SPDiv(SPFlt(RADIUS) , SPFlt(1));
basex -= RADIUS;
basey -= RADIUS;
twelve = SPFlt(12);
l.x.i = SPSub(SPFlt(cx) , light.x.i); /* translate light source to */
l.y.i = SPSub(SPFlt(cy) , light.y.i); /* make center of sphere the */
l.z.i = SPSub(SPFlt(cz) , light.z.i); /* origin relative to light */
normalize(&l);
for (scanline = 0; scanline < 2 * RADIUS; scanline++) {
register int r;
register int i;
r = displacements[scanline];
y = scanline + basey;
pnt.y.i = SPMul(SPFlt(RADIUS - scanline) , rad.i);
bres(r , surface);
for (i = 0; i < 2 * r; i++) {
pnt.x.i = SPMul(SPFlt(-r + i) , rad.i);
pnt.z.i = SPMul(SPFlt(surface[i]) , rad.i);
d.i = SPAdd(SPMul(pnt.x.i , l.x.i) , SPMul(pnt.y.i, l.y.i));
d.i = SPAdd(d.i , SPMul(pnt.z.i , l.z.i));
I = AMBIENT;
tmp.i = SPTieee(d.i);
if (tmp.f > 0.0) {
I += SPFix(SPMul(d.i , SPFlt(NMAP - AMBIENT)));
H.x.i = l.x.i;
H.y.i = l.y.i;
H.z.i = SPAdd(SPFlt(1) , l.z.i);
normalize(&H);
/* reusing d */
d.i = SPAdd(SPMul(H.x.i , pnt.x.i), SPMul(H.y.i , pnt.y.i));
d.i = SPAdd(d.i, SPMul(H.z.i , pnt.z.i));
d.i = SPPow(twelve , d.i);
tmp.i = SPTieee(d.i);
if (tmp.f > 0.0) I += SPFix(SPMul(d.i , twelve));
}
x = RADIUS - r + i + basex;
if (I >= NMAP) I = NMAP - 1;
SetAPen(rp , I);
(void) WritePixel(rp , x , y);
}
}
}
allocate_rasters()
{
int i , j;
for (i = 0; i < NSTEPS; i++) {
InitRastPort(&left[i].rp);
InitRastPort(&right[i].rp);
InitBitMap(&left[i].bm , DEPTH , D , D);
InitBitMap(&right[i].bm , DEPTH , D , D);
for (j = 0; j < DEPTH; j++) {
left[i].bm.Planes[j] = AllocRaster(D , D);
if (left[i].bm.Planes[j] == NULL) {
outer: if (is_cli) printf("cannot allocate raster space\n");
close_things();
exit(1);
}
rastcount++;
right[i].bm.Planes[j] = AllocRaster(D , D);
if (right[i].bm.Planes[j] == NULL) goto outer;
rastcount++;
}
left[i].rp.BitMap = &left[i].bm;
right[i].rp.BitMap = &right[i].bm;
SetRast(&left[i].rp , 0);
SetRast(&right[i].rp , 0);
}
}
deallocate_rasters()
{
int i , j;
for (i = 0; i < NSTEPS && rastcount >= 0; i++) {
for (j = 0; j < DEPTH && rastcount >= 0; j++) {
if (rastcount-- == 0) continue;
FreeRaster(left[i].bm.Planes[j] , D , D);
if (rastcount-- == 0) continue;
FreeRaster(right[i].bm.Planes[j] , D , D);
}
}
}